/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.support;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.core.metrics.StartupStep;
import org.springframework.lang.Nullable;

import java.util.*;

/**
 * Delegate for AbstractApplicationContext's post-processor handling.
 *
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 4.0
 */
final class PostProcessorRegistrationDelegate {

	private PostProcessorRegistrationDelegate() {
	}


	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		//初始化一个set列表，存储已经执行过的beanName
		Set<String> processedBeans = new HashSet<>();
		//类型断言：如果是BeanDefinitionRegistry类型的
		//意思就是：当前 beanFactory 是 beanDefinition 的注册中心 ， bd 全部注册到 bf。
		if (beanFactory instanceof BeanDefinitionRegistry) {
			//类型转换 bf -> bd注册中心
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			//存储BeanFactoryPostProcessor
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			/*存储BeanDefinitionRegistryPostProcessor*/
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			/**
			 * BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 之间的关系 ？
			 * BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子类。
			 * 它里面 搞了一个新的方法  postProcessBeanDefinitionRegistry ，可以往容器中注册更多的bd信息。
			 * 扩展点：
			 * ①BeanFactoryPostProcessor 对bd信息进行修改
			 * ②postProcessBeanDefinitionRegistry 添加更多的bd信息
			 */

			//处理ApplicationContext里面硬编码注册的beanFactoryPostProcessor
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				/*如果当前后置处理器的类型是BeanDefinitionRegistryPostProcessor*/
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					/*将后置处理器转换为BeanDefinitionRegistryPostProcessor类型*/
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					/*执行后置处理器的方法   这里又是一个后置处理器的调用点*/
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					/*将执行完的后置处理器加入到集合中*/
					registryProcessors.add(registryProcessor);
				} else {/*此时说明后置处理器是一个BeanFactoryPostProcessor，直接加入到BeanFactoryPostProcessor的集合中。后续统一执行。*/
					regularPostProcessors.add(postProcessor);
				}
			}

			// 这里不要初始化FactoryBeans:我们需要保留所有常规bean的未初始化状态，
			// 让bean工厂的后处理器应用于它们！在实现优先级的bean definition registry后处理器、
			// Ordered、Ordered等之间进行分离。
			/*当前阶段的registry后置处理器集合*/
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// 首先执行实现了主排序接口的后置处理器  PriorityOrdered
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				/*判断对应的bean是否实现了主排序接口，如果实现了，就让该后置处理器添加到集合。*/
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					/*已经执行的后置处理器名字集合，因为接下来马上要执行这些后置处理器了。*/
					processedBeans.add(ppName);
				}
			}
			/*对后置处理器进行排序  根据 getOrder() 返回的值进行升序排序*/
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			/*注册所有的后置处理器*/
			registryProcessors.addAll(currentRegistryProcessors);
			/*调用当前后置处理器的相关接口方法 执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry()*/
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			/*清空当前阶段临时的集合*/
			currentRegistryProcessors.clear();

			// 接着执行实现了Ordered接口的后置处理器 这里的后置处理器是普通排序后置处理器
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				/*确保每一个后置处理器只执行一次*/
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// 最后将剩下的后置处理器逐个执行
			/*这个变量控制是否需要循环*/
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				/*从bean工厂拿BeanDefinitionRegistryPostProcessor的后置处理器*/
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				/*循环判断执行没执行过得*/
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						/*这里为什么吧变量设置为true？因为新注册的后置处理器，可能也是往容器中注册的 registry 类型的后置处理器*/
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
				currentRegistryProcessors.clear();
			}
			/*这里是执行BeanDefinitionRegistryPostProcessor 的父类 BeanFactoryPostProcessor 的方法*/
			// 上面重复三遍是为了执行 BeanDefinitionRegistryPostProcessor 的方法，
			// 但是，BeanDefinitionRegistryPostProcessor 还继承了 BeanFactoryPostProcessor
			// 这里是为了执行所有后置处理器的
			// （BeanFactoryPostProcessor）的 postProcessBeanFactory方法。
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			/*这个方法就是执行BeanFactoryPostProcessor的方法*/
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}
		/*处理不是 BeanDefinitionRegistry 类型的后置处理器*/
		else {
			// 调用上下文实例注册的后置处理器
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}


		/**
		 * 上面处理的是硬编码的BeanDefinitionRegistry和BeanFactoryPostProcessor的后置处理器。
		 * 下面处理器的是普通的后置处理器。
		 */

		// 不要在这里初始化FactoryBeans:我们需要保留所有常规beans未初始化以让bean工厂后处理器应用于它们！
		/*获取容器内注册的所有BeanFactoryPostProcessor集合。还是处理主排序，普通排序，为排序的后置处理器集合*/
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// 在实现优先级有序、有序和其他的BeanFactoryPostProcessors之间进行分离。
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			/*包含说明已经执行过了，直接啥也不做跳过即可*/
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// 首先，执行带有优先级接口的
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// 接着执行实现了order接口的
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 最后执行其他剩余的
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// 内存清理，帮助GC
		beanFactory.clearMetadataCache();

		/*思考：为什么spring要把这里代码逻辑写的这么麻烦？为了框架的健壮性，提供更好的扩展性，方便在不同阶段，针对不同的需求进行扩展。*/
	}

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {


		//获取到所有的BeanPostProcessor后置处理器的beanName数组
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// 注册bean后置处理器检查器，当bean在bean后置处理器实例化期间创建时，
		// 即当bean不适合被所有bean后置处理器处理时，它会记录一条信息。
		/*后置处理器数量，计算方式beanFactory已经有的数量+1+后注册的。1？下面一行手动硬加的*/
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		/*BeanPostProcessorChecker？ step into 检查创建bean实例的时候，后置处理器是否已经全部注册完毕，如果未完毕，日志提示。*/
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// 分离 实现了主排序接口的后置处理器
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		/*存放mergedBeanDefinition后置处理器*/
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		/*普通排序接口的*/
		List<String> orderedPostProcessorNames = new ArrayList<>();
		/*没有实现排序接口的*/
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		/*循环将所有的后置处理器进行分离存放*/
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// 首先注册实现了优先级接口的后置处理器
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// 其次，注册实现了order接口的后置处理器
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// 最终，注册所有剩下的所有后置处理器
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//注册后置处理器的逻辑 step into
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// 最后，再次处理internalPostProcessors，确保存放mergedBeanDefinition后置处理器在链表的末尾
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		//重新注册后处理器时，将内部beans检测为ApplicationListeners，将其移动到处理器链的末端(用于获取代理等)。
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

	private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
		// Nothing to sort?
		if (postProcessors.size() <= 1) {
			return;
		}
		Comparator<Object> comparatorToUse = null;
		if (beanFactory instanceof DefaultListableBeanFactory) {
			comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
		}
		if (comparatorToUse == null) {
			comparatorToUse = OrderComparator.INSTANCE;
		}
		postProcessors.sort(comparatorToUse);
	}

	/**
	 * Invoke the given BeanDefinitionRegistryPostProcessor beans.
	 */
	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
					.tag("postProcessor", postProcessor::toString);
			postProcessor.postProcessBeanDefinitionRegistry(registry);
			postProcessBeanDefRegistry.end();
		}
	}

	/**
	 * Invoke the given BeanFactoryPostProcessor beans.
	 */
	private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
			StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
					.tag("postProcessor", postProcessor::toString);
			postProcessor.postProcessBeanFactory(beanFactory);
			postProcessBeanFactory.end();
		}
	}

	private static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
		//如果是抽象bean工厂
		if (beanFactory instanceof AbstractBeanFactory) {
			// 给抽象bean工厂绑定后置处理器
			((AbstractBeanFactory) beanFactory).addBeanPostProcessors(postProcessors);
		}
		else {//此时的前置条件：一定不是抽象bean工厂
			//循环给bean工厂绑定后置处理器
			for (BeanPostProcessor postProcessor : postProcessors) {
				beanFactory.addBeanPostProcessor(postProcessor);
			}
		}
	}


	/**
	 * BeanPostProcessor that logs an info message when a bean is created during
	 * BeanPostProcessor instantiation, i.e. when a bean is not eligible for
	 * getting processed by all BeanPostProcessors.
	 */
	private static final class BeanPostProcessorChecker implements BeanPostProcessor {

		private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);

		private final ConfigurableListableBeanFactory beanFactory;

		private final int beanPostProcessorTargetCount;

		public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
			this.beanFactory = beanFactory;
			this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
		}

		@Override
		public Object postProcessBeforeInitialization(Object bean, String beanName) {
			return bean;
		}
		/*主要的执行逻辑就是这里*/
		@Override
		public Object postProcessAfterInitialization(Object bean, String beanName) {
			/*
			* 条件一成立：说明当前bean的类型就不是一个后置处理器
			* 条件二成立：当前bean不是spring本身的bean，是用户级别的bean。
			* 条件三成立：当前beanFactory已经注册的后置处理器的数量小于后置处理器的总数，说明后置处理器还没注册完。当前bean初始化的比较早，打一行日志。
			* */
			if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
					this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
				if (logger.isInfoEnabled()) {
					logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
							"] is not eligible for getting processed by all BeanPostProcessors " +
							"(for example: not eligible for auto-proxying)");
				}
			}
			return bean;
		}

		private boolean isInfrastructureBean(@Nullable String beanName) {
			if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {
				BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
				return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE);
			}
			return false;
		}
	}

}
